﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;

namespace 多线程学习
{
    public partial class Form1 : Form
    {



        public Form1()
        {
            InitializeComponent();
        }

        #region//异步委托示例
        //声明委托
        delegate int DoSomethingDelegate(int parameter);
        //声明调用方法
        private int DoSomething(int parameter)
        {
            int i = 0;
            while (i < parameter * 10)
            {
                i++;
                Console.WriteLine(String.Format("doSomething{0}:次数{1}", parameter, i));
            }
            return i;
        }

        //声明回调函数
        private void DoSomethingCallback(IAsyncResult result)
        {

            DoSomethingDelegate doSomething = result.AsyncState as DoSomethingDelegate;

            int i = doSomething.EndInvoke(result);

            Console.WriteLine(i);

        }

        //异步委托调用
        private void btn委托_Click(object sender, EventArgs e)
        {
            List<IAsyncResult> results = new List<IAsyncResult>();
            for (int i = 0; i < 10; i++)
            {
                DoSomethingDelegate doSomething = new DoSomethingDelegate(DoSomething);
                IAsyncResult result = doSomething.BeginInvoke(i, new AsyncCallback(DoSomethingCallback), doSomething);
                results.Add(result);
            }
            results.ForEach(t => { while (!t.IsCompleted) { Thread.Sleep(500); } });
        }
        #endregion

        #region//控件委托示例         主要应用于WinForm绘图(解决绘图卡顿)
        //声明委托
        delegate void DoFormDelegate(Form parameter);
        //声明调用方法
        private void DoForm(Form parameter)
        {
            parameter.Text = "控件委托";
        }
        //异步委托调用
        private void btn控件委托_Click(object sender, EventArgs e)
        {
            DoFormDelegate doSomething = new DoFormDelegate(DoForm);
            this.BeginInvoke(doSomething, new object[] { this });
        }
        #endregion

        #region//Thread线程示例
        //声明带参数线程方法(主要参数类型必须为object,方法必须为无返回类型)
        private void DoSomethingObject(object obj)
        {

            int j = int.Parse(obj + "");
            for (int i = 0; i < j; i++)
            {
                Console.WriteLine(i);
            }
        }

        //声明无参数线程方法
        private void DoSomethingObject()
        {
            for (int i = 0; i < 50; i++)
            {
                Console.WriteLine(i);
            }
        }

        //声明线程调用
        private void btnThread_Click(object sender, EventArgs e)
        {
            //有参调用
            Thread thread1 = new Thread(new ParameterizedThreadStart(DoSomethingObject));
            thread1.Start(100);
            while (thread1.ThreadState == ThreadState.Running)
            {
                Thread.Sleep(500);
            }
            //无参调用
            Thread thread2 = new Thread(new ThreadStart(DoSomethingObject));
            thread2.Start();
            while (thread2.ThreadState == ThreadState.Running)
            {
                Thread.Sleep(500);
            }
        }
        #endregion 

        #region//ThreadPool调用示例
        //声明方法(主要参数类型必须为object,方法必须为无返回类型)
        private void DoWaitCallback(object obj)
        { 
            int j = int.Parse(obj + "");
            for (int i = 0; i < j; i++)
            {
                Console.WriteLine(i);
            }
        }

        //声明ThreadPool调用
        private void btnThreadpool_Click(object sender, EventArgs e)
        { 
            for (int i = 0; i < 10; i++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(DoWaitCallback), i);
            }
        }
        #endregion


        #region//Task调用示例
        //声明调用方法
        public int DoTask(int parameter) { 
            parameter = parameter * parameter;
            Console.WriteLine(String.Format("运行值{0};", parameter));
            return parameter;
        } 
        //Task调用
        private void btnTask_Click(object sender, EventArgs e)
        {
            //有返回值调用
            List<Task<int>> taskList = new List<Task<int>>();
            for (int i = 0; i < 10; i++)
            {
                //注意由于闭包，必须在循环里声明变量中转，否则传值会出错
                int j = i;
                Task<int> task =  Task.Factory.StartNew( () => DoTask(j));
                taskList.Add(task);
            } 
            Task.WaitAll(taskList.ToArray()); 
            List<int> results = new List<int>();
            taskList.ForEach(t => results.Add( t.Result)); 
            foreach (int result in results) { 
                Console.WriteLine(String.Format("返回值{0};", result));
            }

            //无返回值调用
            List<Task> taskList1 = new List<Task>();
            for (int i = 0; i < 10; i++)
            {
                //注意由于闭包，必须在循环里声明变量中转，否则传值会出错
                int j = i;
                Task task = Task.Factory.StartNew(() => DoTask(j));
                taskList1.Add(task);
            }
            Task.WaitAll(taskList1.ToArray());

        }
        #endregion

        #region//BackgroundWorker示例 主要用于在多线程中及时更新界面控件
        //声明参数类
        class MyArg {
            public String Key { get; set; }
            public object Value { get; set; }
        }

        //处理业务
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            MyArg arg = e.Argument as MyArg;
            for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(500);
                arg.Value = i;  
                this.backgroundWorker1.ReportProgress(i+1, arg);
            }
            
            
        }
        //进度显示,并对界面控件进行修改,解决跨线程修改控件错误
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            MyArg a = e.UserState as MyArg;

            this.label1.Text =  String.Format("{0}",a.Key);
            this.label2.Text = String.Format("{0}", a.Value);

            progressBar1.Value = e.ProgressPercentage;

        }
        //调用BackGroundWork.RunWorkerAsync
        private void btnBackGroundWork_Click(object sender, EventArgs e)
        {

            MyArg arg = new MyArg(); 
            arg.Key = "Key";
            arg.Value = 1; 
            this.backgroundWorker1.RunWorkerAsync(arg);
        }
        #endregion

    }
}
